#include "CapitalMarketCNEXForm.h"
#include "ui_CapitalMarketCNEXForm.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDate>
#include <qmath.h>
#include <widgets/STips.h>

const int kMinBarWidth = 4; //最小宽度
const int kMaxBarWidth = 16; //最大宽度
const float kXSpacerCoefficient = 1.25;

const int kMinYInterval = 8;
const char kHeightUints[4] = {10, 20, 50, 100};

CapitalMarketCNEXForm::CapitalMarketCNEXForm(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::CapitalMarketCNEXForm)
{
    ui->setupUi(this);

    setMouseTracking(true);
    setAttribute(Qt::WA_Hover,true);

    const QString chkBoxQss =
        "QCheckBox::indicator { margin-left: 8px; width: 8px; height: 8px; background-color: #%1; }"
        "QCheckBox::indicator:unchecked { background-color: grey; }"
        ;

    QCheckBox* legend_widgets[MaxCount] = {ui->AllMaket, ui->BigBank, ui->SmallBank, ui->NotBank};
    for (int i = 0; i < MaxCount; ++i) {
        legend_widgets[i]->setStyleSheet(chkBoxQss.arg(kBarColor[i].rgba(), 0, 16));
        connect(legend_widgets[i], &QCheckBox::clicked, this, &CapitalMarketCNEXForm::legendClicked);
    }
}

CapitalMarketCNEXForm::~CapitalMarketCNEXForm()
{
    delete ui;
}

void CapitalMarketCNEXForm::clearData()
{
    for(int i = 0; i < kMaxTimestampCount; ++i) {
        for (int j=0; j<MaxCount; ++j) {
            BarHeight[i][j]=0;
        }
    }
    update();
}

void CapitalMarketCNEXForm::setData(int TimestampIndex, char* BarHeights)
{
    if ((TimestampIndex<0) || (TimestampIndex>=kMaxTimestampCount))
        return;
    for (int j=0; j<MaxCount; ++j) {
        BarHeight[TimestampIndex][j]=BarHeights[j];
    }

    const char* max_height = std::max_element(&BarHeight[0][0], &BarHeight[kMaxTimestampCount][0]);
    setMaxHeight(*max_height);
    update();
}

void CapitalMarketCNEXForm::legendClicked(bool checked)
{
    update();
}

void CapitalMarketCNEXForm::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    drawGridAndBar(&painter);
}

int/*widget_height*/ CalcBarHeight(char real, char max, int total_height) {
    return total_height * real / max ;
}

int/*widget_height*/ CalcBarWidth(int bar_count, int total_width) {
    int barWidth = (1.0f * total_width) / (kXSpacerCoefficient + bar_count) ;
    barWidth = qMin(barWidth, kMaxBarWidth);
    barWidth = qMax(barWidth, kMinBarWidth);

    return barWidth;
}

void CapitalMarketCNEXForm::mouseMoveEvent(QMouseEvent *event)
{
    const QPoint mousePos = event->pos();
    QWidget::mouseMoveEvent(event);

    const QCheckBox* legend_widgets[MaxCount] = {ui->AllMaket, ui->BigBank, ui->SmallBank, ui->NotBank};
    const int checkedLedendCount = std::count_if(legend_widgets, legend_widgets+MaxCount, [](const QCheckBox* chk)->bool {
        return chk->isChecked();
    });

    const QLabel* labelXs[kMaxTimestampCount] = {ui->labelX0, ui->labelX1, ui->labelX2, ui->labelX3};
    int i = 0;
    for (i = 0; i < kMaxTimestampCount; ++i) {
        const QLabel* X= labelXs[i];
        const int& center = X->x() + X->width()/2;
        const int barWidth = CalcBarWidth(checkedLedendCount, X->width());

        //check mouse hover
        QRect labelXRect{center -  barWidth * checkedLedendCount/2, 0, barWidth * checkedLedendCount, height()};
        const bool hover = labelXRect.contains(mousePos);
        if (hover) {
            break;
        }
    }

    // bar area hightlight changed
    if (HoverLabelX != i) {
        HoverLabelX = i;
        update();
    }

    if (HoverLabelX != kMaxTimestampCount) {
        const QCheckBox* lengend_widgets[MaxCount] = {ui->AllMaket, ui->BigBank, ui->SmallBank, ui->NotBank};
        QString szTips = QDate::currentDate().toString("MM-dd ");
        szTips.append(labelXs[HoverLabelX]->text());
        for (int type=0; type < MaxCount; ++type) {
            if (lengend_widgets[type]->isChecked())
                szTips.append(QString("\n%1 %2").arg(lengend_widgets[type]->text()).arg(int(BarHeight[HoverLabelX][type])));
        }

        std::vector<qb::QBTipCustomItem> vctCustomItem;
        qb::QBTipCustomItem item;
        item.clrNormal = QColor(223, 174, 76, 255);
        item.col = 1;

        for (int i = 0; i < 4; i++)
        {
            item.row = i + 1;
            vctCustomItem.push_back(item);
        }

        qb::QBTips::showText(event->screenPos().toPoint(), szTips, this, &vctCustomItem);
    } else {
        qb::QBTips::hideTip();
    }
}

void CapitalMarketCNEXForm::setMaxHeight(int h)
{
    int Ylabel_count = qMax(5, qCeil(0.1f * h));
    Ylabel_count = qMin(10, Ylabel_count);

    MaxHeight = Ylabel_count * 10;
}

typedef struct {
    int height;
    QColor color;
} tBarInfo;

void CapitalMarketCNEXForm::drawGridAndBar(QPainter *p)
{
    QPen pen(QColor(53, 57, 59));
    pen.setWidth(1);
    p->setPen(pen);

    const QRect rect{ ui->chartAreaLayout->geometry()};
    int i = 0;
    const int kNPos = sizeof(kHeightUints)/sizeof(kHeightUints[0]);
    for (; i < kNPos; ++i) {
        if (rect.height() * kHeightUints[i] / MaxHeight > kMinYInterval)
            break;
    }
    if (i == kNPos)
        return;

    const char heightUnit = kHeightUints[i];
    const int  YInterval = rect.height() * heightUnit / MaxHeight;

    const int bottom = rect.bottom();
    {
        const QFont& f = ui->labelX0->font();
        //const int fontHeight = ui->labelX0->fontMetrics().height();
        p->setFont(f);

        QPen pen2(ui->labelX0->palette().color(QPalette::Text));
        for(i = 0; ; ++i) {
            const int y = bottom - i*YInterval;
            p->setPen(pen);
            p->drawLine(QPoint{rect.left(), y}, QPoint{rect.right(), y});

            if (i*heightUnit >= MaxHeight)
                break;

            p->setPen(pen2);
            p->drawText(QPoint{rect.left(), y - 1}, std::to_string(i*heightUnit).c_str());
        }
        p->setPen(pen);
    }
    const int top = bottom - i*YInterval;

    const QCheckBox* legend_widgets[MaxCount] = {ui->AllMaket, ui->BigBank, ui->SmallBank, ui->NotBank};
    const QLabel* labelXs[kMaxTimestampCount] = {ui->labelX0, ui->labelX1, ui->labelX2, ui->labelX3};

    const int max_value = MaxHeight;
    for (int col = 0; col < kMaxTimestampCount; ++col) {
        const QLabel* X = labelXs[col];
        const int& center = X->x() + X->width()/2;
        p->drawLine(QPoint{center, top}, QPoint{center, bottom});

        //check mouse hover
        const bool hover = (HoverLabelX == col);

        QVector<tBarInfo> vecBars;
        vecBars.reserve(MaxCount);
        //draw Bars
        for(int i = 0; i < MaxCount; ++i) {
            if (!legend_widgets[i]->isChecked())
                continue;

            tBarInfo bar;
            bar.height = CalcBarHeight(BarHeight[col][i], max_value, bottom - top);
            bar.color = kBarColor[i];
            if (hover)
                bar.color.setAlpha(255);
            vecBars.push_back(bar);
        }

        if (!vecBars.empty()) {
            const int barWidth = CalcBarWidth(vecBars.size(), X->width());
            int left = center - (barWidth * vecBars.size())/2;
            for (const tBarInfo& bar: vecBars) {
                QRect barRect{left,  bottom - bar.height, barWidth, bar.height};
                p->fillRect(barRect, bar.color);

                left += barWidth;
            }
        }
    }
}

